package collection;

import exception.CollectionEmptyException;
import exception.CollectionFullException;

public class ArrayStack<E> implements IStack<E>{

	public static final int DEFAULT_CAPACITY = 10;
	private E[] internalArray;
	private int topIndex;
	
	public ArrayStack()
	{
		this.internalArray = (E[]) new Object[DEFAULT_CAPACITY];
		this.topIndex = -1;
	}
	
	public ArrayStack(int capacity)
	{
		this.internalArray = (E[]) new Object[capacity];
		this.topIndex = -1;
	}
	
	@Override
	public boolean isEmpty() 
	{
		return this.topIndex == -1;
	}

	@Override
	public int size() 
	{
		return this.topIndex + 1;
	}
	
	private boolean isFull()
	{
		return this.topIndex == this.internalArray.length - 1;
	}

	@Override
	public void push(E element) 
	{
		if (isFull())
		{
			throw new CollectionFullException("Stack");
		}
		else
		{
			this.topIndex += 1;
			this.internalArray[this.topIndex] = element;
		}
	}

	@Override
	public E pop() throws CollectionEmptyException 
	{
		if (isEmpty())
		{
			throw new CollectionEmptyException("Stack");
		}
		else
		{
			E retVal = this.internalArray[this.topIndex];
			this.internalArray[this.topIndex] = null;
			this.topIndex -= 1;
			
			return retVal;
		}
	}

	@Override
	public E top() throws CollectionEmptyException 
	{
		if (isEmpty())
		{
			throw new CollectionEmptyException("Stack");
		}
		else
		{
			return this.internalArray[this.topIndex];
		}
	}
	
	@Override
	public String toString()
	{
		if (isEmpty())
			return "[]";
		
		String retStr = "[ ";
		for (int i=0; i<=this.topIndex; i++)
		{
			if (i == this.topIndex)
			{
				retStr += this.internalArray[i];
			}
			else
			{
				retStr += this.internalArray[i] + ", ";
			}
		}
		retStr += " ]";
		
		return retStr;
	}
}
